package com.gitee.wsl.scheduler.job.context

import com.gitee.wsl.scheduler.job.bean.BaseJob
import com.gitee.wsl.scheduler.job.bean.Job
import com.gitee.wsl.scheduler.job.bean.JobProps
import com.gitee.wsl.scheduler.job.bean.ScheduledJob
import com.gitee.wsl.scheduler.job.repository.JobRepository
import com.gitee.wsl.logger.Logger
import com.gitee.wsl.logger.debug
import com.gitee.wsl.logger.defaultLoggerFactory
import kotlinx.coroutines.CoroutineScope
import kotlin.coroutines.CoroutineContext


open class JobContext<J : BaseJob> internal constructor(
    override val coroutineContext: CoroutineContext,
    scheduledJob: ScheduledJob,
    private val jobRepository: JobRepository
) : CoroutineScope {
    private val internalJobId = scheduledJob.id
    val jobId = scheduledJob.settings.id
    val logger: Logger = Logger.defaultLoggerFactory("it.justwrote.kjob.${scheduledJob.settings.name}#${scheduledJob.settings.id}")

    private var stepProgress = scheduledJob.progress.step

    suspend fun setInitialMax(max: Int): Boolean = setInitialMax(max.toLong())

    suspend fun setInitialMax(max: Long): Boolean =
        jobRepository.setProgressMax(internalJobId, max)

    suspend fun step(step: Int): Boolean = step(step.toLong())

    suspend fun step(step: Long = 1L): Boolean {
        stepProgress += step
        return jobRepository.stepProgress(internalJobId, step)
    }

    internal suspend fun start(): Boolean {
        logger.debug("Start execution")
        return jobRepository.startProgress(internalJobId)
    }

    internal suspend fun complete(): Boolean {
        logger.debug("Complete execution")
        val b1 = jobRepository.setProgressMax(internalJobId, stepProgress)
        val b2 = jobRepository.completeProgress(internalJobId)
        return b1 && b2
    }

    internal suspend fun scheduledJob(): ScheduledJob = jobRepository.get(internalJobId)!!
}

class JobContextWithProps<J : Job> internal constructor(
    coroutineContext: CoroutineContext,
    val props: JobProps<J>,
    scheduledJob: ScheduledJob,
    jobRepository: JobRepository
) : JobContext<J>(coroutineContext, scheduledJob, jobRepository)